#!/bin/sh

# define the base path of project.
CUR_PATH=$(cd "$(dirname "$0")" && pwd)
SPARROW_BASE_PATH=$CUR_PATH

# cd base dir of project.
# the process is in the same shell as the starting shell.
cd $SPARROW_BASE_PATH

# extract command
COMMAND=$1
if [ "${COMMAND}" = "start" ]; then
    VAR_IS_START_COMMAND=true
elif [ "${COMMAND}" = "restart" ]; then
    VAR_IS_RESTART_COMMAND=true
elif [ "${COMMAND}" = "stop" ]; then
    VAR_IS_STOP_COMMAND=true
elif [ "${COMMAND}" = "startone" ]; then
    VAR_IS_STARTONE_COMMAND=true
elif [ "${COMMAND}" = "stopone" ]; then
    VAR_IS_STOPONE_COMMAND=true
elif [ "${COMMAND}" = "updateone" ]; then
    VAR_IS_UPDATEONE_COMMAND=true
elif [ "${COMMAND}" = "status" ] || [ "${COMMAND}" = "stats" ]; then
    VAR_IS_STATUS_COMMAND=true
    VAR_RUNTIME_NO_PRINT_MESSAGE="ON" # no print message
elif [ "${COMMAND}" = "help" ] || [ "${COMMAND}" = "--help" ] || [ "${COMMAND}" = "h" ] || [ "${COMMAND}" = "-h" ]; then
    VAR_IS_HELP_COMMAND=true
    VAR_RUNTIME_NO_PRINT_MESSAGE="ON" # no print message
else
    echo "not support command: ${COMMAND} (Unknown command: ${COMMAND})"
    exit 1
fi

# include sdk of sparrow.
. .work/include/sdk.sh

# do sparrow hook
hook() {
    # hook {hook_type} {service}
    hook_file="$2/hooks/$1.sh"
    if [ -f "${hook_file}" ]; then
        print_info "do hook: ${hook_file}"
        . "${hook_file}"
    fi
}

# start one service.
startone() {
    print_info "sparrow start one..."

    print_stage "do service stop..."
    stopone $1

    print_stage "do before_start hook..."
    hook $CONST_HOOK_BEFORE_START $1

    print_stage "do pull/build sparrow-app-$1 images..."
    pull_or_build_app_image $1

    print_stage "do compose..."
    if ! docker-compose --env-file $CONST_SPARROW_CONFIG_ENV_FILE up -d --no-deps "$1"; then
        print_error "$1 compose failed"
        exit 1
    fi

    print_stage "do after_start hook..."
    hook $CONST_HOOK_AFTER_START $1

    print_info "sparrow startone successfully"
}

# stop one service.
stopone() {
    print_info "sparrow stop one..."

    print_stage "do before_stop hook..."
    hook $CONST_HOOK_BEFORE_STOP $1

    container_name="sparrow_container_${CONTAINER_NAMESPACE}_${1}"
    print_stage "do docker stop: ${container_name}..."
    docker stop "$container_name"

    print_stage "do after_stop hook..."
    hook $CONST_HOOK_AFTER_STOP $1
}

# update one service.
updateone() {
    print_info "sparrow update one..."

    print_stage "do service stopone..."
    stopone $1

    print_stage "do clear service..."
    clear_service_resources $1

    print_stage "do before_start hook..."
    hook $CONST_HOOK_BEFORE_START $1

    # build app image
    print_stage "do build sparrow-app-${1} image..."
    if ! . "./${1}/make_app_image/run.sh"; then
        print_error "failed to build sparrow-app-${1} image"
        exit 1
    fi

    print_stage "do compose..."
    if ! docker-compose --env-file $CONST_SPARROW_CONFIG_ENV_FILE up -d --no-deps "$1"; then
        print_error "$1 compose failed"
        exit 1
    fi

    print_stage "do after_start hook..."
    hook $CONST_HOOK_AFTER_START $1

    print_info "sparrow update one successfully"
}

# start all services.
start() {
    print_info "sparrow start all..."
    
    for service in "${ENABLE_SERVICE_LIST[@]}"; do
        print_info "current service: $service"

        print_stage "do service stop..."
        stopone $service

        print_stage "do service start..."
        startone $service
    done

    print_info "sparrow start successfully"
}

# stop all services.
stop() {
    print_info "sparrow stop all..."

    for service in "${ENABLE_SERVICE_LIST[@]}"; do
        print_info "current service: $service"

        print_stage "do service stop..."
        stopone $service
    done

    print_info "sparrow stop successfully"
}

# restart sparrow
restart() {
    start
}

# watch status
status() {
    running_container_stdout=$(docker container ls --format "container_id: {{.ID}} => image: {{.Image}} => port: [{{.Ports}}] => container_name: {{.Names}}" | grep 'sparrow')
    if [ "$running_container_stdout" != "" ]; then
        echo "status: running"
    else
        echo "status: not running"
    fi
    echo "working dir: $(pwd)"

    printf "====================ENV=========================\n"
    echo "CONTAINER_NAMESPACE: $CONTAINER_NAMESPACE"
    echo "ENABLE_SERVICE_LIST: ${ENABLE_SERVICE_LIST[@]}"
    if [ "$running_container_stdout" != "" ]; then
        printf "====================Services====================\n"
        echo "$running_container_stdout"
    fi
}

# help document.
help() {
    # sparrow's help command
    printf "welcome to sparrow\n"
    printf "\n"
    printf "1、Control all service.\n"
    printf "(1) stop all services: ./sparrow stop\n"
    printf "(2) start all services: ./sparrow start\n"
    printf "(3) restart all services: ./sparrow restart\n"
    printf "\n"
    printf "2、Control one service.\n"
    printf "(1) stop one service: ./sparrow stopone {service_name}\n"
    printf "(2) start one service: ./sparrow startone {service_name}\n"
    printf "(3) update one service: ./sparrow updateone {service_name}\n"
    printf "\n"
    printf "4、Container helper.\n"
    printf "(1) enter all containers(Automatically open all required resources): ./sparrow enter\n"
    printf "(2) enter one container: ./sparrow enter {service_name}\n"
    printf "\n"
}

# before run sparrow command.
before_sparrow_command() {
    print_info "do before_sparrow_command..."

    # check docker.
    if ! docker info > /dev/null 2>&1; then
        print_error "error: please install or start docker first."
        echo "==================================================================================="
        print_warn "Reference: https://github.com/WGrape/sparrow/tree/main/.work/extra/doc/5.QA_EN.md\n"
        print_warn "Tip: use 'docker info' to check status of docker, and use 'systemctl start docker' to start.\n"
        exit 1
    fi

    # check ip.
    local_ip=$(ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | sed 's/,$//' | head -n 1)
    if [ "$local_ip" != "$DOCKER_HOST_IP" ]; then
        print_warn "your ip: before=$DOCKER_HOST_IP, after=$local_ip"

        DOCKER_HOST_IP=$local_ip  # update environment DOCKER_HOST_IP
        if is_mac; then
            sed -i '' "s/^DOCKER_HOST_IP=.*/DOCKER_HOST_IP=${DOCKER_HOST_IP}/g" "${CONST_SPARROW_CONFIG_ENV_FILE}"
        elif is_linux; then
            sed -i "s/^DOCKER_HOST_IP=.*/DOCKER_HOST_IP=${DOCKER_HOST_IP}/g" "${CONST_SPARROW_CONFIG_ENV_FILE}"
        else
            print_error "your local ip changed, please modify DOCKER_HOST_IP in the ${CONST_SPARROW_CONFIG_ENV_FILE} file"
            exit 1
        fi
    fi
}

# after run sparrow command.
after_sparrow_command() {
    print_info "do after_sparrow_command..."
}

##################### start script exec flow #####################

# before run sparrow command.
before_sparrow_command

# when run sparrow command.
COMMAND=$1
# core commands.
if [ "${VAR_IS_START_COMMAND}" = true ]; then
    start
elif [ "${VAR_IS_RESTART_COMMAND}" = true ]; then
    restart
elif [ "${VAR_IS_STOP_COMMAND}" = true ]; then
    stop
elif [ "${VAR_IS_STARTONE_COMMAND}" = true ] || [ "${VAR_IS_STOPONE_COMMAND}" = true ] || [ "${VAR_IS_UPDATEONE_COMMAND}" = true ]; then
    if [ "$2" == "" ]; then
        print_error "check param error: miss service param"
        exit 1
    fi

    if [ "${VAR_IS_STARTONE_COMMAND}" = true ]; then
        startone "$2"
    elif [ "${VAR_IS_STOPONE_COMMAND}" = true ]; then
        stopone "$2"
    elif [ "${VAR_IS_UPDATEONE_COMMAND}" = true ]; then
        updateone "$2"
    fi
elif [ "${VAR_IS_STATUS_COMMAND}" = true ]; then
    status
elif [ "${VAR_IS_HELP_COMMAND}" = true ]; then
    help
fi

# after run sparrow command.
after_sparrow_command

##################### end script exec flow #######################
